package zelix.managers;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import zelix.Core;
import zelix.eventapi.event.EventPlayerPost;
import zelix.eventapi.event.EventPlayerPre;
import zelix.gui.clickguis.gishcode.ClickGuiScreen;
import zelix.gui.clickguis.gishcode.theme.dark.DarkTheme;
import zelix.hack.Hack;
import zelix.hack.HackCategory;
import zelix.hack.hacks.automine.AutoMine;
import zelix.hack.hacks.external.External;
import zelix.hack.hacks.hud.HUD;
import zelix.hack.hacks.irc.IRCChat;
import zelix.hack.hacks.xray.AntiAntiXrayMod;
import zelix.value.Mode;
import zelix.value.ModeValue;
import zelix.value.Value;
import zelix.utils.Wrapper;

import net.minecraft.init.SoundEvents;
import net.minecraftforge.client.event.*;
import net.minecraftforge.event.entity.ProjectileImpactEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import zelix.hack.hacks.*;

public class HackManager {

	private static Hack toggleHack = null;
	public static ArrayList<Hack> hacks;
	public static HashMap<Hack,Object> pluginhacks;
	private GuiManager guiManager;
	private ClickGuiScreen guiScreen;

	public HackManager() {
		hacks = new ArrayList<Hack>();
		addHack(new Disabler());
		addHack(new Targets());
		addHack(new Enemys());
		addHack(new Teams());
		addHack(new Glowing());
		addHack(new Trajectories());
		addHack(new EntityESP());
		addHack(new ItemESP());
		addHack(new ChestESP());
		addHack(new Tracers());
		addHack(new WallHack());
		addHack(new FastUse());
		addHack(new Flight());
		addHack(new ServerCrasher());
		addHack(new NightVision());
		addHack(new Profiler());
		addHack(new AntiBot());
		addHack(new AntiItemLag());
		addHack(new AimAssist());
		addHack(new BowAimBot());
		addHack(new Trigger());
		addHack(new Criticals());
		addHack(new KillAura());
		addHack(new Velocity());
		addHack(new AutoSprint());
		addHack(new AutoArmor());
		addHack(new InteractClick());
		addHack(new Regen());
		addHack(new FastPlace());
		addHack(new ChestStealer());
		addHack(new Glide());
		addHack(new Nuker());
		addHack(new AntiFall());
		addHack(new Ghost());
		addHack(new Blink());
		addHack(new Scaffold());
		addHack(new FastLadder());
		addHack(new Speed());
		addHack(new AutoStep());
		addHack(new AntiSneak());
		addHack(new FreeCam());
		addHack(new BlockOverlay());
		addHack(new PluginsGetter());
		addHack(new AttackPacketCW());
		addHack(new AttackPacketCIA());
		addHack(new Teleport());
		addHack(new FireballReturn());
		addHack(new SkinStealer());
		addHack(new GuiWalk());
		addHack(new PlayerRadar());
		addHack(new SkinChanger());
		addHack(new Parkour());
		addHack(new AntiRain());
		addHack(new AntiWeb());
		addHack(new Spider());
		addHack(new AutoEat());
		addHack(new AutoWalk());
		addHack(new AutoSwim());
		addHack(new AutoTotem());
		addHack(new AutoShield());
		addHack(new Rage());
		addHack(new Suicide());
		addHack(new SelfDamage());
		addHack(new Hitbox());
		addHack(new AntiAfk());
		addHack(new TestHack());
		addHack(new FastBreak());
		addHack(new Disconnect());
		addHack(new GhostMode());
		addHack(new SelfKick());
		addHack(new PortalGodMode());
		addHack(new PickupFilter());
		addHack(new PacketFilter());
		addHack(new FakeCreative());
		addHack(new ArmorHUD());
		addHack(new HUD());
		addHack(new HighJump());
		addHack(new ClickGui());
		addHack(new CommandFrame());
		addHack(new CommandGetter());
		addHack(new TpAura());
		addHack(new AutoTool());
		addHack(new BedNuker());
		addHack(new Cilp());
		addHack(new LongJump());
		addHack(new NoSlow());
		addHack(new NoSwing());
		addHack(new SafeWalk());
		addHack(new Fall());
		addHack(new AutoSoup());
		addHack(new SuperKick());
		addHack(new Timer());
		addHack(new IRCChat());
		addHack(new BlinkAttack());
		addHack(new AutoMine());
		addHack(new Search());
		addHack(new Reach());
		addHack(new AutoClicker());
		addHack(new AntiHunger());
		addHack(new CloudConfig());
		addHack(new EnemyInfo());
		addHack(new SelfDestruct());
		addHack(new AttackSpeed());
		addHack(new FastBow());
		addHack(new AntiAntiXrayMod());
		addHack(new ItemTeleport());
		if (Core.Love.equals("External")){
			addHack(new External());
		}

	}

	public void setGuiManager(GuiManager guiManager) {
		this.guiManager = guiManager;
	}

	public ClickGuiScreen getGui() {
		if (this.guiManager == null) {
			this.guiManager = new GuiManager();
			this.guiScreen = new ClickGuiScreen();
			ClickGuiScreen.clickGui = this.guiManager;
			this.guiManager.Init();
			this.guiManager.setTheme(new DarkTheme());
		}
		return this.guiManager;
	}

	public static Hack getHack(String name) {
		Hack hack = null;
		for (Hack h : getHacks()) {
			if (h.getName().toLowerCase().equalsIgnoreCase(name.toLowerCase())) {
				hack = h;
			}
		}
		return hack;
	}

	public static List<Hack> getSortedHacks() {
		final List<Hack> list = new ArrayList<Hack>();
		for (final Hack hack : getHacks()) {
			if (hack.isToggled()) {
				if (!hack.isShow()) {
					continue;
				}
				list.add(hack);
			}
		}
		list.sort(new Comparator<Hack>()
		{
			@Override
			public int compare(final Hack h1, final Hack h2) {
				String s1 = h1.getRenderName();
				String s2 = h2.getRenderName();

				for (Value value : h1.getValues()) {
					if (value instanceof ModeValue) {
						ModeValue modeValue = (ModeValue) value;
						if (!modeValue.getModeName().equals("Priority")) {
							for (Mode mode : modeValue.getModes()) {
								if (mode.isToggled()) {
									s1 = s1 + " " + mode.getName();


								}
							}
						}
					}
				}
				for (Value value : h2.getValues()) {
					if (value instanceof ModeValue) {
						ModeValue modeValue = (ModeValue) value;
						if (!modeValue.getModeName().equals("Priority")) {
							for (Mode mode : modeValue.getModes()) {
								if (mode.isToggled()) {
									s2 = s2 + " " + mode.getName();
								}
							}
						}
					}
				}
				final int cmp = Wrapper.INSTANCE.fontRenderer().getStringWidth(s2)
						- Wrapper.INSTANCE.fontRenderer().getStringWidth(s1);
				return (cmp != 0) ? cmp : s2.compareTo(s1);
			}
		});
		return list;
	}
	public void sortModules() {
		hacks.sort((m1, m2) -> {
			if (m1.getName().toCharArray()[0] > m2.getName().toCharArray()[0]) {
				return 1;
			}
			return -1;
		});

	}

	public static List<Hack> getSortedHacks3() {
		final List<Hack> list = new ArrayList<Hack>();
		for (final Hack module : getHacks()) {
			if (module.isToggled()) {
				if (!module.isShow()) {
					continue;
				}
				list.add(module);
			}
		}
		list.sort(new Comparator<Hack>() {
			@Override
			public int compare(final Hack h1, final Hack h2) {
				String s1 = h1.getRenderName();
				String s2 = h2.getRenderName();
				for (Value value : h1.getValues()) {
					if (value instanceof ModeValue) {
						ModeValue modeValue = (ModeValue) value;
						if (modeValue.getModeName().equals("Mode")) {
							for (Mode mode : modeValue.getModes()) {
								if (mode.isToggled()) {
									s1 = s1 + " " + mode.getName();
								}
							}
						}
					}
				}
				for (Value value : h2.getValues()) {
					if (value instanceof ModeValue) {
						ModeValue modeValue = (ModeValue) value;
						if (modeValue.getModeName().equals("Mode")) {
							for (Mode mode : modeValue.getModes()) {
								if (mode.isToggled()) {
									s2 = s2 + " " + mode.getName();
								}
							}
						}
					}
				}

				final int cmp = (int) (HUD.font.getFont("SFB 6").getWidth(s2) - HUD.font.getFont("SFB 6").getWidth(s1));
				return (cmp != 0) ? cmp : s2.compareTo(s1);
			}
		});
		return list;
	}
	public static void addHack(Hack hack) {
		hacks.add(hack);
	}

	public static void addPluginHack(Hack hack,Object obj) {
		pluginhacks.put(hack,obj);
		hacks.add(hack);
	}

	public static void unregist(Hack hack,Object obj) {
		pluginhacks.get(obj);
		hacks.add(hack);
	}



	public static ArrayList<Hack> getHacks() {
		return hacks;
	}

	public static Hack getToggleHack() {
		return toggleHack;
	}

	public static void onKeyPressed(int key) {
		if (Wrapper.INSTANCE.mc().currentScreen != null) {
			return;
		}
		for (Hack hack : getHacks()) {
			if (hack.getKey() == key) {
				hack.toggle();
				Wrapper.INSTANCE.player().playSound(SoundEvents.BLOCK_WOOD_BUTTON_CLICK_ON, 0.15F,
						hack.isToggled() ? 0.7F : 0.6F);
				toggleHack = hack;

			}
		}
	}

	public static void onGuiContainer(GuiContainerEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onGuiContainer(event);
			}
		}
	}

	public static void onGuiOpen(GuiOpenEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onGuiOpen(event);
			}
		}
	}

	public static void onRender3D(RenderBlockOverlayEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onRender3D(event);
			}
		}
	}

	public static void onMouse(MouseEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onMouse(event);
			}
		}
	}

	public static void onLeftClickBlock(PlayerInteractEvent.LeftClickBlock event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onLeftClickBlock(event);
			}
		}
	}

	public static void onCameraSetup(EntityViewRenderEvent.CameraSetup event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onCameraSetup(event);
			}
		}
	}

	public static void onAttackEntity(AttackEntityEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onAttackEntity(event);
			}
		}
	}

	public static void onProjectileImpact(ProjectileImpactEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onProjectileImpact(event);
			}
		}
	}

	public static void onItemPickup(EntityItemPickupEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onItemPickup(event);
			}
		}
	}

	public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onPlayerTick(event);
			}
		}
	}

	public static void onClientTick(TickEvent.ClientTickEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onClientTick(event);
			}
		}
	}

	public static void onLivingUpdate(LivingEvent.LivingUpdateEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onLivingUpdate(event);
			}
		}
	}

	public static void onRenderWorldLast(RenderWorldLastEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onRenderWorldLast(event);
			}
		}
	}

	public static void onRenderGameOverlay(RenderGameOverlayEvent.Text event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onRenderGameOverlay(event);
			}
		}
	}

	public static void onInputUpdate(InputUpdateEvent event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onInputUpdate(event);
			}
		}
	}

	public static void onPlayerEventPre(EventPlayerPre event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onPlayerEventPre(event);
			}
		}
	}

	public static void onPlayerEventPost(EventPlayerPost event) {
		for (Hack hack : getHacks()) {
			if (hack.isToggled()) {
				hack.onPlayerEventPost(event);
			}
		}
	}

	public static List<Hack> getModulesInType(HackCategory t) {
		ArrayList<Hack> output = new ArrayList<Hack>();
		ArrayList<Hack> hack = new ArrayList<>();
		hack.addAll(hacks);
		for (Hack m : hacks) {
			if (m.getCategory() != t)
				continue;
			output.add(m);
		}
		return output;
	}
}
